# -*- coding: utf-8 -*-
# @Time    : 2024/8/29 22:00
# @Author  : Alvin
# @File    : minio_client.py
from io import BytesIO

from flask import current_app
from minio import Minio
from minio.error import InvalidResponseError
from app.libs.error_code import MinioError

class MinioClient:
    def __init__(self, endpoint, access_key, secret_key, secure=False):
        self.endpoint = endpoint
        self.access_key = access_key
        self.secret_key = secret_key
        self.secure = secure
        # 错误记录， 这里secure需要位置传参， 但是kimi生成的没有位置传参，导致secure没有正确初始化为False，而是默认值True，
        # 因此出现了SSL错误
        self.client = Minio(self.endpoint, self.access_key, self.secret_key, secure=self.secure)

    def remove_file(self, bucket_name, object_name):
        """
        从 MinIO 删除文件。
        """
        try:
            self.client.remove_object(bucket_name, object_name)
            return True
        except InvalidResponseError as e:
            current_app.logger.error(f"Error removing file: {e}")
            return False

    def put_object_with_data(self, bucket_name, object_name, data, content_type='application/octet-stream'):
        """
        直接向 MinIO 存储桶写入数据。
        :param bucket_name: 存储桶名称
        :param object_name: 对象名称（即存储在 MinIO 中的文件名）
        :param data: 要写入的字节数据
        :param content_type: 数据的 MIME 类型（默认为二进制流）
        """
        try:
            self.client.put_object(bucket_name, object_name, data, len(data), content_type)
            return True
        except InvalidResponseError as e:
            current_app.logger.error(f"Error writing data to object: {e}")
            return False

    def upload_file(self, file, bucket_name, object_name=None):
        """
        上传文件到 MinIO。
        :param file: Flask 的 FileStorage 对象
        :param bucket_name: MinIO 存储桶名称
        :param object_name: 存储在 MinIO 中的对象名称（文件名）
        """
        if object_name is None:
            object_name = file.filename

        try:
            # 使用 FileStorage 对象的 stream 属性读取文件内容
            file_content = file.stream.read()
            # 使用 BytesIO 将字节内容转换为一个可读的输入流
            file_stream = BytesIO(file_content)
            self.client.put_object(
                bucket_name=bucket_name,
                object_name=object_name,
                data=file_stream,
                length=len(file_content)
            )
            return True
        except InvalidResponseError as e:
            print(f"Error occurred: {e}")
            raise MinioError()

    def download_file(self, bucket_name, object_name):
        """
        从 MinIO 下载文件并作为响应发送给客户端。
        :param bucket_name: 存储桶名称
        :param object_name: 对象名称（即在 MinIO 中的文件名）
        """
        try:
            # 获取文件对象
            response = self.client.get_object(bucket_name, object_name)
            data = BytesIO()
            # 读取数据并写入 BytesIO 对象
            for chunk in response.stream(8192):
                data.write(chunk)
            data.seek(0)  # 重置指针到文件开始位置
            return data

        except InvalidResponseError as e:
            current_app.logger.error(f"Error downloading file: {e}")
            # 可以抛出异常或返回错误信息
            raise MinioError()
